home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / Presentations / Closures, Observers, Properties / Cop Notes next >
Text File  |  2000-06-22  |  4KB  |  138 lines

  1. Model and View Design
  2.  
  3. The model does the work; views display and control the model
  4. Ideally, the model doesn't know about the views.
  5. Views can know about the model, but the less they know, the more reusable they are.
  6.  
  7. Today's goal: provide objects which connect the model to the views
  8. while minimizing the dependencies between them.
  9.  
  10. Closures
  11.  
  12. The first problem is easy: how do we connect a pushbutton to a method
  13. of the model?
  14.  
  15. First try: give the button a function pointer to call:
  16.         void (*toCall)()
  17.  
  18. That works well from the point of view of the button class, but is difficult
  19. to connect to a model, which likely provides a member function, not a
  20. plain function. So how do we make the button call model.Method()?
  21.  
  22. Second try: instead of a function pointer, use an object with an operator()
  23.  
  24.  
  25. <Code>
  26.  
  27.  
  28.  
  29. That works, but it's not very general -- it can only be used for
  30. one method of the Model class.  We can allow it to call an arbitrary
  31. method by using a pointer to a member function:
  32.  
  33.  
  34. <Code>
  35.  
  36.  
  37.  
  38. But we're still wedded to a particular Model class.  We'd like
  39. the Closure to be able to call a method of any class.  So we'll
  40. remove the dependencies on the model class in stages.  We can
  41. remove one dependency in the data by storing a void* instead
  42. of a Model*:
  43.  
  44.  
  45. <Code>
  46.  
  47.  
  48.  
  49. We'd like to do the same for the method member.  But a pointer to a member
  50. function does not convert to a void*.  Instead, we'll convert it to
  51. a pointer to a member function of a class we'll make up, called "Generic."
  52. It's safe to do that as long as we convert it back to the original
  53. type before calling it:
  54.  
  55.  
  56. <Code>
  57.  
  58.  
  59.  
  60. Now the data members don't depend on the Model class.  But the
  61. member functions still do.  But we can make Model a template
  62. parameter to get around that:
  63.  
  64.  
  65. <Code>
  66.  
  67.  
  68.  
  69. Now we have another problem: there's one operator() for each Model type.
  70. And if the one we call isn't the one the Closure was constructed with,
  71. we'll probably crash.  So we'll do better to record which function to
  72. call when the Closure is constructed:
  73.  
  74.  
  75. <Code>
  76.  
  77.  
  78.  
  79. That's the one that works.  But we'll throw in one more change -- we'll
  80. make Closure a template based on the type of function pointer it
  81. resembles.  To do that, we'll declare a general template without a
  82. definition, and provide partial specializations for different lengths
  83. of the parameter list:
  84.  
  85.  
  86. <Code>
  87.  
  88.  
  89. Observables
  90.  
  91. Next, consider a view which needs to be informed of events in the
  92. model.  As an example, take a standard file dialog, which responds
  93. to the mounting of a new disk.  The model shouldn't simply call
  94. a view through a closure -- it shouldn't even know whether it has
  95. a view that needs to be called.
  96.  
  97. Instead, we'd like to think of the views as observing events in
  98. the model.  When an event occurs in the model, it broadcasts
  99. a message to all observers.  To do this, we give the model
  100. a class which holds a list of observers.  Again, we template
  101. the class on the signature of the message the model sends.
  102.  
  103.  
  104. <Code>
  105.  
  106.  
  107.  
  108. Properties
  109.  
  110. Now consider a view that both reads and changes a value.  This comes
  111. up particularly often in AppleScript, and they even use the same name
  112. for this sort of connection that I will: a property.
  113.  
  114. A good example of a property is the "zoomed" state of a window.
  115. From AppleScript, you can ask whether a window is zoomed, and you can
  116. also tell a window to be zoomed or not.  The property acts like a
  117. boolean variable, but there's often not really a variable there.
  118. So our property class will act like a reference to a variable.
  119.  
  120.  
  121. <Code>
  122.  
  123.  
  124.  
  125.  
  126. Observable Properties
  127.  
  128. Finally, the majority of user-interface objects need three kinds
  129. of communication with the model.  They need to read the current
  130. state, make changes to the state, and be notified when the state
  131. changes.  To cover all three bases, we combine the Property and
  132. Observable templates.
  133.  
  134.  
  135. <Code>
  136.  
  137.  
  138.